パフォーマンスプロファイリング
モバイル アプリに関しては、パフォーマンスはユーザー エクスペリエンスにとって非常に重要です。 ユーザーは、アプリがスムーズなスクロールと意味のあるアニメーションを備えていることを期待しています。 「ジャンク」として知られる、途切れやフレームのスキップ。アプリが確実に動作することを確認する方法 さまざまなデバイスでジャンクは発生していませんか?
オプションは 2 つあります。まず、別のデバイスでアプリを手動でテストします。 このアプローチは小規模なアプリでは機能するかもしれませんが、より多くのアプリになると、 アプリのサイズが大きくなると面倒になります。あるいは、統合を実行します 特定のタスクを実行し、パフォーマンスのタイムラインを記録するテスト。 次に、結果を調べて、特定のセクションが アプリを改善する必要があります。
このレシピでは、パフォーマンスを記録するテストの作成方法を学びます。 特定のタスクの実行中にタイムラインを表示し、その概要を保存します。 結果をローカル ファイルに保存します。
このレシピでは次の手順を使用します。
- 項目のリストをスクロールするテストを作成します。
- アプリのパフォーマンスを記録します。
- 結果をディスクに保存します。
- テストを実行します。
- 結果を確認します。
1. 項目のリストをスクロールするテストを作成します。
このレシピでは、アプリがスクロールするときのパフォーマンスを記録します。 アイテムのリスト。パフォーマンス プロファイリングに焦点を当てるために、このレシピは次のように構築します。 でスクロールウィジェットテストのレシピ。
そのレシピの指示に従ってアプリを作成し、テストを作成します。 すべてが期待どおりに動作することを確認します。
2. アプリのパフォーマンスを記録する
次に、アプリがスクロールするときのパフォーマンスを記録します。
リスト。このタスクを実行するには、traceAction()
によって提供されるメソッドIntegrationTestWidgetsFlutterBinding
クラス。
このメソッドは、提供された関数を実行し、Timeline
アプリのパフォーマンスに関する詳細情報が含まれます。この例
項目のリストをスクロールする機能を提供します。
特定の項目が表示されていることを確認します。機能が完了すると、
のtraceAction()
レポートデータを作成しますMap
が含まれているTimeline
。
を指定します。reportKey
複数実行する場合traceAction
。
デフォルトではすべてTimelines
キーと一緒に保存されますtimeline
、
この例では、reportKey
に変更されますscrolling_timeline
。
await binding.traceAction(
() async {
// Scroll until the item to be found appears.
await tester.scrollUntilVisible(
itemFinder,
500.0,
scrollable: listFinder,
);
},
reportKey: 'scrolling_timeline',
);
3. 結果をディスクに保存します
パフォーマンスのタイムラインを取得したので、それを確認する方法が必要です。
のTimeline
オブジェクトはすべてのイベントに関する詳細情報を提供します
それは実行されましたが、結果を確認する便利な方法はありません。
したがって、変換すると、Timeline
にTimelineSummary
。
のTimelineSummary
2 つのタスクを実行できるため、作業が簡単になります
結果を確認するには:
- 含まれるデータを要約した json ドキュメントをディスクに書き込む
以内
Timeline
。この概要には、 スキップされたフレームの数、最も遅いビルド時間など。 - 完了したものを保存する
Timeline
ディスク上の json ファイルとして。 このファイルは Chrome ブラウザで開くことができます。 トレースツールは次の場所にありますchrome://tracing
。
結果をキャプチャするには、という名前のファイルを作成します。perf_driver.dart
の中にtest_driver
フォルダーに移動し、次のコードを追加します。
import 'package:flutter_driver/flutter_driver.dart' as driver;
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() {
return integrationDriver(
responseDataCallback: (data) async {
if (data != null) {
final timeline = driver.Timeline.fromJson(data['scrolling_timeline']);
// Convert the Timeline into a TimelineSummary that's easier to
// read and understand.
final summary = driver.TimelineSummary.summarize(timeline);
// Then, write the entire timeline to disk in a json format.
// This file can be opened in the Chrome browser's tracing tools
// found by navigating to chrome://tracing.
// Optionally, save the summary to disk by setting includeSummary
// to true
await summary.writeTimelineToFile(
'scrolling_timeline',
pretty: true,
includeSummary: true,
);
}
},
);
}
のintegrationDriver
関数にはresponseDataCallback
カスタマイズできます。
デフォルトでは、結果はintegration_response_data.json
ファイル、
ただし、この例のような概要を生成するようにカスタマイズできます。
4. テストを実行する
パフォーマンスをキャプチャするためにテストを構成した後Timeline
そして保存します
結果の概要をディスクに保存するには、次のコマンドを使用してテストを実行します。
flutter drive \
--driver=test_driver/perf_driver.dart \
--target=integration_test/scrolling_test.dart \
--profile
の--profile
オプションはアプリを「プロファイル モード」用にコンパイルすることを意味します
「デバッグ モード」ではなく、ベンチマーク結果がより近くなるようにします。
エンドユーザーが体験するもの。
5. 結果を確認する
テストが正常に完了すると、build
のルートにあるディレクトリ
プロジェクトには 2 つのファイルが含まれています。
-
scrolling_summary.timeline_summary.json
概要が含まれています。開ける テキスト エディタを使用してファイルに含まれる情報を確認します 内部。より高度な設定を使用すると、次の間隔で概要を保存できます。 テストの実行時間を計測し、結果のグラフを作成します。 -
scrolling_timeline.timeline.json
完全なタイムライン データが含まれています。 次の場所にある Chrome ブラウザのトレース ツールを使用してファイルを開きます。chrome://tracing
。トレース ツールが提供するのは、 タイムライン データを検査して発見するための便利なインターフェイス パフォーマンスの問題の原因。
まとめの例
{
"average_frame_build_time_millis": 4.2592592592592595,
"worst_frame_build_time_millis": 21.0,
"missed_frame_build_budget_count": 2,
"average_frame_rasterizer_time_millis": 5.518518518518518,
"worst_frame_rasterizer_time_millis": 51.0,
"missed_frame_rasterizer_budget_count": 10,
"frame_count": 54,
"frame_build_times": [
6874,
5019,
3638
],
"frame_rasterizer_times": [
51955,
8468,
3129
]
}
完全な例
統合テスト/スクロールテスト.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:scrolling/main.dart';
void main() {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Counter increments smoke test', (tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp(
items: List<String>.generate(10000, (i) => 'Item $i'),
));
final listFinder = find.byType(Scrollable);
final itemFinder = find.byKey(const ValueKey('item_50_text'));
await binding.traceAction(
() async {
// Scroll until the item to be found appears.
await tester.scrollUntilVisible(
itemFinder,
500.0,
scrollable: listFinder,
);
},
reportKey: 'scrolling_timeline',
);
});
}
test_driver/perf_driver.dart
import 'package:flutter_driver/flutter_driver.dart' as driver;
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() {
return integrationDriver(
responseDataCallback: (data) async {
if (data != null) {
final timeline = driver.Timeline.fromJson(data['scrolling_timeline']);
// Convert the Timeline into a TimelineSummary that's easier to
// read and understand.
final summary = driver.TimelineSummary.summarize(timeline);
// Then, write the entire timeline to disk in a json format.
// This file can be opened in the Chrome browser's tracing tools
// found by navigating to chrome://tracing.
// Optionally, save the summary to disk by setting includeSummary
// to true
await summary.writeTimelineToFile(
'scrolling_timeline',
pretty: true,
includeSummary: true,
);
}
},
);
}